<?php

namespace App\Console\Scripts\Counter;

use App\Consts\GlobalConst;
use App\Consts\GlobalCounterConst;
use App\Models\Cache\CacheKey;
use App\Models\FakeNote;
use App\Models\SysComment;
use App\Models\SysNote;
use App\Models\SysReply;
use App\Models\UserCollect;
use App\Models\UserMessageLikeSend;
use Illuminate\Database\Query\Builder;

/**
 * 笔记计数统计脚本
 * Class ArticleCounterCommand
 * @package App\Console\Scripts\Counter
 */
class NoteCounterCommand extends BaseCounterCommand
{

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'counter:note {action}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'counter for note';

    /**
     * 笔记点赞统计
     * @return int
     */
    public function like()
    {
        $subMode = $this->_getSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish) {
            foreach ($list as $item) {
                static $index = 1;
                $id = $item->note_id;
                $count = UserMessageLikeSend::getSubModel(function (Builder $query) use ($id) {
                    $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
                    $query->where('target_type', GlobalConst::TARGET_TYPE_NOTE);
                    $query->where('target_id', $id);
                }, ['id'])->count();
                $fake = FakeNote::getModel()
                    ->where(['action_type' => GlobalCounterConst::ACTION_TYPE_LIKE])
                    ->where('note_id', $id)
                    ->value('count') ? : 0;
                $total = $count + $fake;
                // set cache
                $cacheKey = $this->setHashCache(
                    ['note_id' => $id],
                    CacheKey::COUNTER_NOTE,
                    [GlobalCounterConst::COUNT_LIKE => $total]
                );
                // log info
                $info = "[$index/$finish] set cache key `$cacheKey` - ".GlobalCounterConst::COUNT_LIKE." {$this->sort} to $count + $fake = (int) $total";
                $this->info($info);
                if ($total) $this->logger($info, false, 'script');
                $index++;
            }
        }, 'note_id');
        return 1;
    }

    /**
     * 笔记评论统计
     * @return int
     */
    public function comments()
    {
        $subMode = $this->_getSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish) {
            foreach ($list as $item) {
                static $index = 1;
                $id = $item->note_id;
                $total = SysComment::getSubModel(function (Builder $query) use ($id) {
                    $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
                    $query->where('target_type', GlobalConst::TARGET_TYPE_NOTE);
                    $query->where('target_id', $id);
                }, ['id', 'comment_id', 'target_id', 'is_deleted'])->count();
                // 评论即使被删除，但是有回复依旧统计
                $comment = SysComment::getSubModel(function (Builder $query) use ($id) {
                    $query->where('is_deleted', GlobalConst::IS_DELETED);
                    $query->where('target_type', GlobalConst::TARGET_TYPE_NOTE);
                    $query->where('target_id', $id);
                }, ['id', 'comment_id', 'target_id', 'is_deleted'])->get();
                if ($comment->isNotEmpty()) {
                    $commentIdAry = $comment->pluck('comment_id');
                    $total += SysReply::getSubModel(function (Builder $query) use ($commentIdAry) {
                        $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
                        $query->whereIn('comment_id', $commentIdAry);
                    }, ['id'])->count() ? : 0;
                }
                // set cache
                $cacheKey = $this->setHashCache(
                    ['note_id' => $id],
                    CacheKey::COUNTER_NOTE,
                    [GlobalCounterConst::COUNT_COMMENT => $total]
                );
                // log info
                $info = "[$index/$finish] set cache key `$cacheKey` - ".GlobalCounterConst::COUNT_COMMENT." {$this->sort} to (int) $total";
                $this->info($info);
                if ($total) $this->logger($info, false, 'script');
                $index++;
            }
        }, 'note_id');
        return 1;
    }

    /**
     * 笔记回复统计
     * @return int
     */
    public function reply()
    {
        $subMode = $this->_getSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish) {
            foreach ($list as $item) {
                static $index = 1;
                $id = $item->note_id;
                $total = SysReply::getSubModel(function (Builder $query) use ($id) {
                    $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
                    $query->where('target_type', GlobalConst::TARGET_TYPE_NOTE);
                    $query->where('target_id', $id);
                }, ['id'])->count();
                // set cache
                $cacheKey = $this->setHashCache(
                    ['note_id' => $id],
                    CacheKey::COUNTER_NOTE,
                    [GlobalCounterConst::COUNT_REPLY => $total]
                );
                // log info
                $info = "[$index/$finish] set cache key `$cacheKey` - ".GlobalCounterConst::COUNT_REPLY." {$this->sort} to (int) $total";
                $this->info($info);
                if ($total) $this->logger($info, false, 'script');
                $index++;
            }
        }, 'note_id');
        return 1;
    }

    /**
     * 笔记收藏统计
     * @return int
     */
    public function collect()
    {
        $subMode = $this->_getSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish) {
            foreach ($list as $item) {
                static $index = 1;
                $id = $item->note_id;
                $total = UserCollect::getSubModel(function (Builder $query) use ($id) {
                    $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
                    $query->where('target_type', GlobalConst::TARGET_TYPE_NOTE);
                    $query->where('target_id', $id);
                }, ['id'])->count();
                // set cache
                $cacheKey = $this->setHashCache(
                    ['note_id' => $id],
                    CacheKey::COUNTER_NOTE,
                    [GlobalCounterConst::COUNT_COLLECT => $total]
                );
                // log info
                $info = "[$index/$finish] set cache key `$cacheKey` - ".GlobalCounterConst::COUNT_COLLECT." {$this->sort} to (int) $total";
                $this->info($info);
                if ($total) $this->logger($info, false, 'script');
                $index++;
            }
        }, 'note_id');
        return 1;
    }

    /**
     * get sub note
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|mixed
     */
    private function _getSubModel()
    {
        $subMode = SysNote::getSubModel(function (Builder $query) {
            $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
            $query->where('is_shield', GlobalConst::IS_NOT_SHIELD);
        }, ['id', 'note_id']);
        return $subMode;
    }

}
